#pragma once

#include <string>
#include <memory>
#include <unordered_map>
#include <mutex>
#include <functional>
#include <vector>
#include <sstream>

struct SubscriberInfo {
    int eventfd;
    std::function<void(const std::string&)> callback;
    std::string topic_name;
    bool is_active;
    
    SubscriberInfo() : eventfd(-1), is_active(false) {}
    SubscriberInfo(int fd, std::function<void(const std::string&)> cb, const std::string& topic)
        : eventfd(fd), callback(cb), topic_name(topic), is_active(true) {}
};

struct PublisherInfo {
    std::string topic_name;
    std::shared_ptr<void> msgq_ptr;
    bool is_active;
    
    PublisherInfo() : is_active(false) {}
    PublisherInfo(const std::string& topic, std::shared_ptr<void> msgq)
        : topic_name(topic), msgq_ptr(msgq), is_active(true) {}
};

class SubInfosManager {
public:
    static SubInfosManager& getInstance() {
        static SubInfosManager instance;
        return instance;
    }
    
    SubInfosManager(const SubInfosManager&) = delete;
    SubInfosManager& operator=(const SubInfosManager&) = delete;
    
    bool registerSubscriber(const std::string& topic_name, const SubscriberInfo& info);
    
    bool unregisterSubscriber(const std::string& topic_name);
    
    SubscriberInfo* getSubscriberInfo(const std::string& topic_name);
    
    bool hasSubscriber(const std::string& topic_name) const;
    
    std::vector<std::string> getActiveTopics() const;
    std::vector<SubscriberInfo> getSubscriberInfos() const;
    
    void cleanup();
    
private:
    SubInfosManager() = default;
    ~SubInfosManager() = default;
    
    mutable std::mutex sub_infos_mutex_;
    std::unordered_map<std::string, SubscriberInfo> sub_infos_;
};

class PubInfosManager {
public:
    static PubInfosManager& getInstance() {
        static PubInfosManager instance;
        return instance;
    }
    
    PubInfosManager(const PubInfosManager&) = delete;
    PubInfosManager& operator=(const PubInfosManager&) = delete;
    
    bool registerPublisher(const std::string& topic_name, const PublisherInfo& info);
    
    bool unregisterPublisher(const std::string& topic_name);
    
    PublisherInfo* getPublisherInfo(const std::string& topic_name);
    
    bool hasPublisher(const std::string& topic_name) const;
    
    std::vector<std::string> getActiveTopics() const;
    std::vector<PublisherInfo> getPublisherInfos() const;
    
    size_t getPublishCount(const std::string& topic_name) const;
    
    void cleanup();
    
private:
    PubInfosManager() = default;
    ~PubInfosManager() = default;
    
    mutable std::mutex pub_infos_mutex_;
    std::unordered_map<std::string, PublisherInfo> pub_infos_;
};

std::string pub_sub_infos_to_string();